/*
 * InputManager.cpp
 */

#include "InputManager.h"

InputManager::InputManager(ifstream* streamV, ifstream* streamE) {
	this->streamV = streamV;
	this->streamE = streamE;
	this->graph = new Graph();
}

void InputManager::processVertexStructure () {
	Logger& logger = Logger::getInstance();
	string output;
	// if stream is open
	if (this->streamV->is_open()) {
		string line;
		int lines = 0;
		// while not end of file
		while(!streamV->eof()) {
			getline (*streamV, line);
			lines++;
			// tokenize with helper class
			int tokenCount = 0;
			string* tokens = Utils::stringTokenize(line, DEFAULT_DELIMITER, tokenCount);
			if (tokenCount < 3){
				output = "Less than 3 elements at line " + Utils::intToString(lines) +" in vertices.txt\n";
				logger  << output;
				output = "Line " + Utils::intToString(lines) +" skiped\n";
				logger << output;
			}
			else {
				if (tokenCount > 3){
					output = "More than 3 elements at line " + Utils::intToString(lines) +" in vertices.txt\n";
					logger << output;
				}
				if (!(Utils::validateFloat(tokens[1])) || !(Utils::validateFloat(tokens[2]))) {
					if (!(Utils::validateFloat(tokens[1]))) {
						output = "Invalid format for position X of the vertex at line " + Utils::intToString(lines) + " in vertices.txt\n";
						logger << output;
						output = "Line " + Utils::intToString(lines) +" skiped\n";
						logger << output;
					}
					else {
						output = "Invalid format for position Y of the vertex at line " + Utils::intToString(lines) +  " in vertices.txt\n";
						logger << output;
						output = "Line " + Utils::intToString(lines) +" skiped\n";
						logger << output;
					}
				}
				else {
					Utils::comaToDot(tokens[1]);
					Utils::comaToDot(tokens[2]);
					float x = Utils::stringToFloat(tokens[1]);
					float y = Utils::stringToFloat(tokens[2]);
					int result = this->graph->createVertex(tokens[0],x,y);
					if (result == ID_REPEATED) {
						output = "There's already a vertex with that ID\n";
						logger  << output;
						output = "Line " + Utils::intToString(lines) +" skiped\n";
						logger << output;
					}
					else if (result == POSITION_REPEATED) {
						output = "There's already a vertex in that x,y position\n";
						logger  << output;
						output = "Line " + Utils::intToString(lines) +" skiped\n";
						logger << output;
					}
					else if (result == MEMORY_ERROR) {
							output = "Error: Not enough memory to create the vertex\n";
							logger  << output;
							output = "Line " + Utils::intToString(lines) +" skiped\n";
							logger << output;	
					} 
				}
			}
			delete[] tokens;
			lines++;
		}
	}
	else {
		output = "Error: file vertices.txt could not be opened\n";
		logger << output;
	}
}

void InputManager::processEdgeStructure () {
	Logger& logger = Logger::getInstance();
	string output;
	// if stream is open
	if (this->streamE->is_open()) {
		int lines = 0;
		string line;
		// while not end of file
		while(!streamE->eof()) {
			getline (*streamE, line);
			lines++;
			// tokenize with helper class
			int tokenCount = 0;
			string* tokens = Utils::stringTokenize(line, DEFAULT_DELIMITER, tokenCount);
			if (tokenCount < 5){
				output = "Less than 5 elements at line " + Utils::intToString(lines) +" in aristas.txt\n";
				logger  << output;
				output = "Line " + Utils::intToString(lines) +" skiped\n";
				logger << output;
			}
			else {
				if (!(Utils::validateFloat(tokens[3])) || !(Utils::validateFloat(tokens[4]))) {
					if (!(Utils::validateFloat(tokens[3]))) {
						output = "Invalid format for the length of the edge at line "  + Utils::intToString(lines) +" in aristas.txt\n";
						logger << output;
						output = "Line " + Utils::intToString(lines) +" skiped\n";
						logger << output;
					}
					else {
						output = "Invalid format for the speed of the edge at line "  + Utils::intToString(lines) +" in aristas.txt\n";
						logger << output;
						output = "Line " + Utils::intToString(lines) +" skiped\n";
						logger << output;
					}
				}
				else {
					Utils::comaToDot(tokens[3]);
					Utils::comaToDot(tokens[4]);
					string lengthPos = tokens[3];
					string speedPos = tokens[4];
					if (tokens[3][0] == '-') {
						output = "Negative length of the edge at line "  + Utils::intToString(lines) +" in aristas.txt\n";
						logger << output;
						output = "Converted to positive\n";
						logger << output;
						lengthPos = Utils::negativeToPositive(tokens[3]); 
					} 
					if (tokens[4][0] == '-') {
						output = "Negative speed of the edge at line "  + Utils::intToString(lines) +" in aristas.txt\n";
						logger << output;
						output = "Converted to positive\n";
						logger << output;
						speedPos = Utils::negativeToPositive(tokens[4]);
					}
					float length = Utils::stringToFloat(lengthPos);
					float speed = Utils::stringToFloat(speedPos);
					if ((length == 0) || (speed == 0)) {
						if (length == 0) {
						output = "Invalid length = 0 of the edge at line " + Utils::intToString(lines) + " in vertices.txt\n";
						logger << output;
						output = "Line " + Utils::intToString(lines) + " skiped\n";
						logger << output;
						}
						else {
						output = "Invalid speed = 0 of the edge at line " + Utils::intToString(lines) + " in vertices.txt\n";
						logger << output;
						output = "Line " + Utils::intToString(lines) + " skiped\n";
						logger << output;
						}
					}
					else {
						int result = this->graph->createEdge(tokens[0],tokens[1],tokens[2],length,speed);
						if (result == ID_REPEATED) {
							output = "There's already an edge with that ID\n";
							logger  << output;
							output = "Line " + Utils::intToString(lines) +" skiped\n";
							logger << output;
						}
						else if (result == VERTEX_NOT_FOUND) {
							output = "The vertex origin or destiny is missing\n";
							logger  << output;
							output = "Line " + Utils::intToString(lines) +" skiped\n";
							logger << output;
						}
						else if (result == MEMORY_ERROR) {
							output = "Error: Not enough memory to create the edge\n";
							logger  << output;
							output = "Line " + Utils::intToString(lines) +" skiped\n";
							logger << output;	
						}
					}
				}
			}
			delete[] tokens;
			lines++;
		}
	}
	else {
		output = "Error: file aristas.txt could not be opened\n";
		logger << output;
	}
}

Graph* InputManager::createGraph() {
	this->processVertexStructure();
	this->processEdgeStructure();
	return this->graph;
}
